package com.ruoyi.web.controller.wechat;

import com.google.common.util.concurrent.RateLimiter;
import com.google.common.util.concurrent.Striped;
import com.ruoyi.bytetopdance.ByteDanceImageTransClient;
import com.ruoyi.bytetopdance.domain.ImageTransResponse;
import com.ruoyi.framework.web.exception.ByteDanceCallException;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.exception.user.UserLimitException;
import com.ruoyi.domain.Image;
import com.ruoyi.service.ITransService;
import com.ruoyi.util.Base64Util;
import com.ruoyi.util.CosClientUtil;
import com.ruoyi.web.controller.wechat.request.TransImageRequest;
import com.ruoyi.web.controller.wechat.response.TransImageResponse;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.ft.v20200304.FtClient;
import com.tencentcloudapi.ft.v20200304.models.FaceCartoonPicRequest;
import com.tencentcloudapi.ft.v20200304.models.FaceCartoonPicResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;

/**
 * 图像处理
 *
 * @author chenchuan2
 * @date 2023-01-12 20:20:17
 */
@RestController
@RequestMapping("/wechat-api/image")
@Slf4j
public class ImageController extends AuthController {

    @Autowired
    private Credential credential;

    @Autowired
    private ITransService transService;

    @Autowired
    private CosClientUtil cosClientUtil;

    @Autowired
    private ByteDanceImageTransClient byteDanceImageTransClient;

    private static AtomicInteger atomicInteger = new AtomicInteger(0);

    private final static Striped<Lock> stripedLocks = Striped.lock(20);

    /**
     * 限流策略 ：1秒钟3个请求
     */
    private final static RateLimiter transLimiter = RateLimiter.create(3.0);


    @PostMapping("/trans")
    @ResponseBody
    public R<TransImageResponse> trans(@Validated @RequestBody TransImageRequest request) throws TencentCloudSDKException, IOException {
        String openId = getOpenId();

        //校验文件大小
        boolean b = Base64Util.checkImageSize(request.getImageBase64(), 5.0D);
        if (!b) {
            log.warn("trans服务图片超过限制");
            throw new UserLimitException();
        }

        //500毫秒内，没拿到令牌，就直接进入服务降级
        boolean tryAcquire = transLimiter.tryAcquire(500, TimeUnit.MILLISECONDS);

        if (!tryAcquire) {
            log.warn("trans进入服务降级");
            throw new UserLimitException();
        }

        Lock lock = stripedLocks.get(openId);
        lock.lock();

        int index = atomicInteger.incrementAndGet();
        TransImageResponse image;

        try {
            //针对同一个用户对base64转hash，判断是否存在
            int i = request.getImageBase64().hashCode();
            Image dataImage = transService.queryUserImage(openId, i + "");
            if (null != dataImage) {
                TransImageResponse response = new TransImageResponse();
                response.setTransId(dataImage.getRequestId());
                response.setTransUrl(dataImage.getTransImg());
                transService.updateImageTime(dataImage);
                return R.ok(response);
            }

            //调用腾讯转换接口
            if (index % 10 == 5) {
                image = tencentTransImage(request.getImageBase64());
            } else {
                image = byteDanceTransImage(request);
            }

            //异步保存数据
            transService.transImage(openId, request, image);
        } finally {
            lock.unlock();
        }

        return R.ok(image);
    }

    @GetMapping("/afterShare")
    public R<TransImageResponse> afterShare(String transId) {
        TransImageResponse response = new TransImageResponse();
        Image image = transService.queryByTransId(transId);
        response.setTransUrl(image.getTransImg());
        response.setTransId(image.getRequestId());
        return R.ok(response);
    }

    @GetMapping("/newest")
    public R<TransImageResponse> newest() {
        String openId = getOpenId();
        TransImageResponse response = new TransImageResponse();
        Image image = transService.queryNewest(openId);
        response.setTransUrl(image.getTransImg());
        response.setTransId(image.getRequestId());
        return R.ok(response);
    }

    private TransImageResponse tencentTransImage(String imageBase64) throws TencentCloudSDKException {
        FtClient client = new FtClient(credential, "ap-beijing");
        // 实例化一个请求对象,每个接口都会对应一个request对象
        FaceCartoonPicRequest req = new FaceCartoonPicRequest();
        req.setImage(imageBase64);
        req.setRspImgType("url");
//        req.setDisableGlobalEffect("true");

        // 返回的resp是一个FaceCartoonPicResponse的实例，与请求对象对应
        FaceCartoonPicResponse resp = client.FaceCartoonPic(req);
        // 输出json格式的字符串回包

        TransImageResponse response = new TransImageResponse();
        response.setTransId(resp.getRequestId());
        response.setTransUrl(resp.getResultUrl());
        return response;
    }

    private TransImageResponse byteDanceTransImage(TransImageRequest request) throws ByteDanceCallException, IOException {
        //base64 上传到腾讯云
        String userImg = cosClientUtil.uploadImgToCos(request.getImageBase64(), request.getFileName());
        ImageTransResponse imageTransResponse = byteDanceImageTransClient.transImage(userImg);

        TransImageResponse response = new TransImageResponse();
        response.setTransId(imageTransResponse.getRequestId());
        response.setTransUrl(imageTransResponse.getImage_url());
        return response;
    }


}
